{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "pipeline：\n",
    "1. 指定一个web url（量子力学的wiki），通过langchain的WebBaseLoader加载；\n",
    "2. 分割成51个片段，每个大小为512个token，两两之间重叠部分为50个token；\n",
    "3. 通过OpenAI的text-embedding-3-small对51个片段进行向量化，并存储在FAISS（向量相似性搜索库）中；\n",
    "4. 设计RAG prompt和RAG chain；\n",
    "5. 测试GPT在有无RAG情况下的表现。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 准备数据\n",
    "### 1.1 加载文档"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "curl: (28) Failed to connect to zh.wikipedia.org port 443 after 133231 ms: 连接超时\n"
     ]
    }
   ],
   "source": [
    "# 检查当前环境能否访问维基百科，超时报错443则需要配置代理。比如在WebBaseLoader()中增加requests_kwargs。\n",
    "! curl https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "from dotenv import load_dotenv\n",
    "load_dotenv() # 在当前路径下新建一个.env文档，其中存储了代理信息\n",
    "\n",
    "HTTP_PROXY = os.getenv(\"HTTP_PROXY\")\n",
    "HTTPS_PROXY = os.getenv(\"HTTPS_PROXY\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "USER_AGENT environment variable not set, consider setting it to identify your requests.\n"
     ]
    }
   ],
   "source": [
    "from langchain_community.document_loaders import WebBaseLoader, DirectoryLoader\n",
    "\n",
    "# 从网页加载\n",
    "loader = WebBaseLoader(\n",
    "    [\"https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA\"],\n",
    "    requests_kwargs={\"proxies\": {\"https\": HTTPS_PROXY}}\n",
    ")\n",
    "# 或从本地文件加载（支持PDF、TXT等）\n",
    "# loader = DirectoryLoader(\"./docs\", glob=\"**/*.txt\")\n",
    "docs = loader.load() # 返回 Document 对象列表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```python\n",
    "# 加载多个网页（传入URL列表）\n",
    "loader = WebBaseLoader([\n",
    "    \"https://example.com/page1\",\n",
    "    \"https://example.com/page2\"\n",
    "])\n",
    "docs = loader.load()  # 返回 Document 对象列表\n",
    "# 遍历所有加载的文档\n",
    "for doc in docs:\n",
    "    print(f\"文档内容：\\n{doc.page_content}\\n\")  # 核心文本内容\n",
    "    print(f\"元数据：\\n{doc.metadata}\\n\")        # 来源URL、标题等元信息\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\n",
      "\n",
      "量子计算机 - 维基百科，自由的\n"
     ]
    }
   ],
   "source": [
    "print(docs[0].page_content[:20])  # 查看前200个字符（避免过长输出）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.2 分割文本\n",
    "分割文本，因为大文档直接处理可能效果不好，所以用 TextSplitter 分成小块。这里可能需要提到 chunk_size 和 chunk_overlap 的参数设置，影响检索效果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "\n",
    "text_splitter = RecursiveCharacterTextSplitter(\n",
    "    chunk_size=512,  # 块大小\n",
    "    chunk_overlap=50  # 块间重叠\n",
    ")\n",
    "splits = text_splitter.split_documents(docs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "51\n"
     ]
    }
   ],
   "source": [
    "print(len(splits))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.3 向量化与存储"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\n",
    "OPENAI_BASE_URL = os.getenv(\"OPENAI_BASE_URL\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import OpenAIEmbeddings\n",
    "\n",
    "# 使用OpenAI Embedding\n",
    "embeddings = OpenAIEmbeddings(\n",
    "    api_key=OPENAI_API_KEY,\n",
    "    base_url=OPENAI_BASE_URL,  # 自定义API地址\n",
    "    model=\"text-embedding-3-small\",  # 根据服务支持的模型调整\n",
    "    timeout=30  # 可选：设置超时时间\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "https://api.openai-hk.com/v1\n",
      "1536\n"
     ]
    }
   ],
   "source": [
    "# 打印客户端配置\n",
    "print(embeddings.openai_api_base)  # 输出: https://your-custom-endpoint.com/v1\n",
    "\n",
    "# 测试Embedding生成\n",
    "text = \"test\"\n",
    "vec = embeddings.embed_query(text)\n",
    "print(len(vec))  # 输出向量维度，如 1536（text-embedding-3-small）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "FAISS（Facebook AI Similarity Search）是 Meta（原 Facebook）开源的高效向量相似性搜索库，专为处理大规模高维向量优化。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.vectorstores import FAISS\n",
    "\n",
    "# 存储到FAISS向量库\n",
    "vectorstore = FAISS.from_documents(splits, embeddings)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 构建检索链\n",
    "### 2.1 定义检索器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "retriever = vectorstore.as_retriever(search_kwargs={\"k\": 3})  # 返回top3结果"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 创建 RAG 提示模板"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "template = \"\"\"基于以下上下文回答问题：\n",
    "{context}\n",
    "\n",
    "问题：{question}\n",
    "\"\"\"\n",
    "prompt = ChatPromptTemplate.from_template(template)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. 生成回答\n",
    "### 3.1 连接模型与检索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "from langchain.schema.runnable import RunnablePassthrough\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "\n",
    "model = ChatOpenAI(\n",
    "    api_key=OPENAI_API_KEY,\n",
    "    base_url=OPENAI_BASE_URL,  # 自定义API地址\n",
    "    model=\"gpt-4-turbo\"\n",
    ")\n",
    "\n",
    "# 构建RAG链\n",
    "rag_chain = (\n",
    "    {\"context\": retriever, \"question\": RunnablePassthrough()} \n",
    "    | prompt \n",
    "    | model \n",
    "    | StrOutputParser()\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "rag_chain 的这段代码使用了 管道式链式调用（LCEL），将检索、提示模板、模型和输出解析器组合成一个完整的 RAG 流程。以下是对其工作原理的逐层拆解：\n",
    "```python\n",
    "rag_chain = (\n",
    "    {\"context\": retriever, \"question\": RunnablePassthrough()}  # Step1: 构建输入\n",
    "    | prompt                    # Step2: 拼接提示词\n",
    "    | model                     # Step3: 调用大模型生成\n",
    "    | StrOutputParser()         # Step4: 解析模型输出为字符串\n",
    ")\n",
    "```\n",
    "(1) 输入构造：{\"context\": retriever, \"question\": RunnablePassthrough()}  \n",
    "作用：定义链的输入格式，包含两个字段：  \n",
    "context：通过 retriever 从向量库检索相关文档块。  \n",
    "question：直接传递用户原始输入（RunnablePassthrough() 表示透传，不做处理）。  \n",
    "(2) 提示模板：prompt  \n",
    "作用：将 context 和 question 填充到预设的模板中，生成最终提问。  \n",
    "(3) 大模型调用：model  \n",
    "作用：将拼接后的提示词发送给大模型（如 GPT-3.5），生成文本回复。  \n",
    "(4) 输出解析：StrOutputParser()  \n",
    "作用：将模型返回的复杂对象（如 AIMessage）解析为纯文本字符串。  \n",
    "\n",
    "链式调用机制（LCEL）  \n",
    "LangChain 通过 | 运算符将多个组件连接成链，数据从左到右流动。每个步骤的输出会作为下一步的输入，类似于 Unix 管道。  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 调用链生成答案"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "量子计算是一种使用量子逻辑进行通用计算的技术。在量子计算中，数据存储和操作的基本单位是量子比特，不同于传统计算机使用的二进制比特。量子比特可以同时表示多种状态，这是因为量子计算利用了量子力学的原理，如叠加和纠缠。叠加允许量子比特同时存在于多种可能状态中，而纠缠则使得多个量子比特可以相互影响。这两种性质使得量子计算机在处理某些特定问题时，例如质因数分解，能够比传统计算机更快速地执行。尽管量子计算机在某些问题上有前所未有的速度优势，但它也有其局限性，只有针对特定已有量子算法的问题，量子计算机才能展示其超凡的计算能力。在其他没有针对量子算法的问题上，其表现可能与传统计算机无异甚至更差。量子计算机目前仍在研发阶段，并且在舆论中有时会被过度渲染。\n"
     ]
    }
   ],
   "source": [
    "response = rag_chain.invoke(\"如何解释量子计算？\")\n",
    "print(response)\n",
    "\n",
    "'''\n",
    "22.3s\n",
    "\n",
    "量子计算是一种使用量子逻辑进行通用计算的技术。在量子计算中，数据存储和操作的基本单位是量子比特，不同于传统计算机使用的二进制比特。量子比特可以同时表示多种状态，这是因为量子计算利用了量子力学的原理，如叠加和纠缠。叠加允许量子比特同时存在于多种可能状态中，而纠缠则使得多个量子比特可以相互影响。这两种性质使得量子计算机在处理某些特定问题时，例如质因数分解，能够比传统计算机更快速地执行。尽管量子计算机在某些问题上有前所未有的速度优势，但它也有其局限性，只有针对特定已有量子算法的问题，量子计算机才能展示其超凡的计算能力。在其他没有针对量子算法的问题上，其表现可能与传统计算机无异甚至更差。量子计算机目前仍在研发阶段，并且在舆论中有时会被过度渲染。\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "content='量子计算是一种基于量子力学原理的计算方式。与传统的计算机使用二进制位（0或1）来存储和处理信息不同，量子计算机使用量子位（或称为量子比特，qubit）来表示和处理信息。\\n\\n量子位的特殊之处在于，它可以同时处于0和1的状态，这种状态叫做叠加态。另外，量子位之间还存在一种特殊的关联，称为纠缠��这使得量子计算机在处理某些特定类型的问题时，比如大数分解、搜索和优化问题，具有潜在的超越传统计算机的计算能力。\\n\\n量子计算机的工作原理依赖于量子位的操控、量子门的应用和量子态的测量。通过精确控制量子位的相互作用和施加特定的量子门（类似于传统计算机中的逻辑门），可以实现复杂的计算过程。最终，通过对量子位进行测量，可以得到计算结果。\\n\\n尽管量子计算具有巨大的潜力，但目前这一领域仍处于研究和开发的初级阶段，制造稳定可靠的量子计算机仍面临诸多技术挑战。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 382, 'prompt_tokens': 16, 'total_tokens': 398, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'gpt-4-turbo', 'system_fingerprint': 'fp_5603ee5e2e', 'finish_reason': 'stop', 'logprobs': None} id='run-bfbb2c53-e6f7-4941-94eb-99a312fb5b59-0' usage_metadata={'input_tokens': 16, 'output_tokens': 382, 'total_tokens': 398, 'input_token_details': {}, 'output_token_details': {}}\n"
     ]
    }
   ],
   "source": [
    "# 无参考资料时，gpt的回复：\n",
    "response = model.invoke(\"如何解释量子计算？\")\n",
    "print(response)\n",
    "\n",
    "'''\n",
    "23.3s\n",
    "\n",
    "content='量子计算是一种基于量子力学原理的计算方式。与传统的计算机使用二进制位（0或1）来存储和处理信息不同，量子计算机使用量子位（或称为量子比特，qubit）来表示和处理信息。\\n\\n量子位的特殊之处在于，它可以同时处于0和1的状态，这种状态叫做叠加态。另外，量子位之间还存在一种特殊的关联，称为纠缠��这使得量子计算机在处理某些特定类型的问题时，比如大数分解、搜索和优化问题，具有潜在的超越传统计算机的计算能力。\\n\\n量子计算机的工作原理依赖于量子位的操控、量子门的应用和量子态的测量。通过精确控制量子位的相互作用和施加特定的量子门（类似于传统计算机中的逻辑门），可以实现复杂的计算过程。最终，通过对量子位进行测量，可以得到计算结果。\\n\\n尽管量子计算具有巨大的潜力，但目前这一领域仍处于研究和开发的初级阶段，制造稳定可靠的量子计算机仍面临诸多技术挑战。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 382, 'prompt_tokens': 16, 'total_tokens': 398, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_name': 'gpt-4-turbo', 'system_fingerprint': 'fp_5603ee5e2e', 'finish_reason': 'stop', 'logprobs': None} id='run-bfbb2c53-e6f7-4941-94eb-99a312fb5b59-0' usage_metadata={'input_tokens': 16, 'output_tokens': 382, 'total_tokens': 398, 'input_token_details': {}, 'output_token_details': {}}\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "messages=[HumanMessage(content=\"基于以下上下文回答问题：\\n[Document(id='c296e22d-f7cf-48d2-b635-6a1a573f2660', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='量子计算机在1980年代多处于理论推导状态。1994年彼得·秀尔提出量子质因数分解算法后[9]，证明量子计算机能运算离散对数[10]，而且速度远胜传统计算机。因为量子不像半导体只能记录0与1，可以同时表示多种状态。如果把半导体比喻成单一乐器，量子计算机就像交响乐团，一次运算可以处理多种不同状况，因此，一部40比特的量子计算机，就能在很短时间内解开1024位计算机花数十年解决的问题。因其对于现在通行于银行及网络等处的RSA加密算法可以破解而构成威胁，量子计算机成了热门话题，除了理论之外，也有不少学者着力于利用各种量子系统来实现量子计算机。'), Document(id='63808346-9353-44c2-a796-2030a7865261', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='量子贝叶斯诠释（英语：Quantum Bayesianism）\\\\n量子生物学\\\\n量子微积分（英语：Quantum calculus）\\\\n量子化学\\\\n量子混沌（英语：Quantum chaos）\\\\n量子认知（英语：Quantum cognition）\\\\n量子宇宙学\\\\n量子微分（英语：Quantum differential calculus）\\\\n量子动力学（英语：Quantum dynamics）\\\\n量子演化（英语：Quantum evolution）\\\\n量子几何（英语：Quantum geometry）\\\\n量子群\\\\n测量问题（英语：Measurement problem）\\\\n量子概率（英语：Quantum probability）\\\\n量子随机演算（英语：Quantum stochastic calculus）\\\\n量子时空（英语：Quantum spacetime）\\\\n量子技术\\\\n量子算法\\\\n量子放大器（英语：Quantum amplifier）\\\\n量子总线（英语：Quantum bus）\\\\n量子点\\\\n量子细胞自动机（英语：Quantum cellular automaton）\\\\n量子有限自动机\\\\n量子通道（英语：Quantum channel）'), Document(id='94163c81-bb75-48b4-beee-623609059199', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='布洛赫球面乃一种对于二阶量子系统之纯态空间的几何表示法，是建立量子计算机的基础。\\\\n量子计算机（英语：Quantum computer）是一种使用量子逻辑进行通用计算的设备。但这与电子计算机（或称传统计算机）不同，量子计算用来存储数据的对象是量子比特，它使用量子算法操作数据。马约拉纳费米子的反粒子就是它自己本身的属性，此或许是促使量子计算机能被制造和实现的一个关键。[1]量子计算机在舆论中有时被过度渲染成无所不能或速度快数亿倍等，其实这种计算机是否强大，需要视问题而定。若该问题已经有提出速算的量子算法，只是仍然存在困难或受限于传统计算机无法执行，那量子计算机确实能达到前所未有的高速；若是没有发明算法的问题，则量子计算机表现与传统计算机无异甚至更差。[2]')]\\n\\n问题：如何解释量子计算？\\n\", additional_kwargs={}, response_metadata={})]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'\\nmessages=[HumanMessage(content=\"基于以下上下文回答问题：\\n[Document(id=\\'3d37ee80-b6f6-40de-89f4-49ee1bc3e943\\', metadata={\\'source\\': \\'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA\\', \\'title\\': \\'量子计算机 - 维基百科，自由的百科全书\\', \\'language\\': \\'zh-Hans-CN\\'}, page_content=\\'量子计算机在1980年代多处于理论推导状态。1994年彼得·秀尔提出量子质因数分解算法后[9]，证明量子计算机能运算离散对数[10]，而且速度远胜传统计算机。因为量子不像半导体只能记录0与1，可以同时表示多种状态。如果把半导体比喻成单一乐器，量子计算机就像交响乐团，一次运算可以处理多种不同状况，因此，一部40比特的量子计算机，就能在很短时间内解开1024位计算机花数十年解决的问题。因其对于现在通行于银行及网络等处的RSA加密算法可以破解而构成威胁，量子计算机成了热门话题，除了理论之外，也有不少学者着力于利用各种量子系统来实现量子计算机。\\'), Document(id=\\'bf4717b8-5808-4c53-8a51-dc883c43da3f\\', metadata={\\'source\\': \\'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA\\', \\'title\\': \\'量子计算机 - 维基百科，自由的百科全书\\', \\'language\\': \\'zh-Hans-CN\\'}, page_content=\\'量子贝叶斯诠释（英语：Quantum Bayesianism）\\\\n量子生物学\\\\n量子微积分（英语：Quantum calculus）\\\\n量子化学\\\\n量子混沌（英语：Quantum chaos）\\\\n量子认知（英语：Quantum cognition）\\\\n量子宇宙学\\\\n量子微分（英语：Quantum differential calculus）\\\\n量子动力学（英语：Quantum dynamics）\\\\n量子演化（英语：Quantum evolution）\\\\n量子几何（英语：Quantum geometry）\\\\n量子群\\\\n测量问题（英语：Measurement problem）\\\\n量子概率（英语：Quantum probability）\\\\n量子随机演算（英语：Quantum stochastic calculus）\\\\n量子时空（英语：Quantum spacetime）\\\\n量子技术\\\\n量子算法\\\\n量子放大器（英语：Quantum amplifier）\\\\n量子总线（英语：Quantum bus）\\\\n量子点\\\\n量子细胞自动机（英语：Quantum cellular automaton）\\\\n量子有限自动机\\\\n量子通道（英语：Quantum channel）\\'), Document(id=\\'77ba01c1-dfd1-4a63-8205-934c458c8d3a\\', metadata={\\'source\\': \\'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA\\', \\'title\\': \\'量子计算机 - 维基百科，自由的百科全书\\', \\'language\\': \\'zh-Hans-CN\\'}, page_content=\\'布洛赫球面乃一种对于二阶量子系统之纯态空间的几何表示法，是建立量子计算机的基础。\\\\n量子计算机（英语：Quantum computer）是一种使用量子逻辑进行通用计算的设备。但这与电子计算机（或称传统计算机）不同，量子计算用来存储数据的对象是量子比特，它使用量子算法操作数据。马约拉纳费米子的反粒子就是它自己本身的属性，此或许是促使量子计算机能被制造和实现的一个关键。[1]量子计算机在舆论中有时被过度渲染成无所不能或速度快数亿倍等，其实这种计算机是否强大，需要视问题而定。若该问题已经有提出速算的量子算法，只是仍然存在困难或受限于传统计算机无法执行，那量子计算机确实能达到前所未有的高速；若是没有发明算法的问题，则量子计算机表现与传统计算机无异甚至更差。[2]\\')]\\n\\n问题：如何解释量子计算？\\n\", additional_kwargs={}, response_metadata={})]\\n'"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 只执行到检索+输入构造\n",
    "from langchain.schema.runnable import RunnablePassthrough\n",
    "\n",
    "partial_chain = ( \n",
    "    {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
    "    | prompt\n",
    ")\n",
    "response = partial_chain.invoke(\"如何解释量子计算？\")\n",
    "print(response)\n",
    "\n",
    "'''\n",
    "messages=[HumanMessage(content=\"基于以下上下文回答问题：\\n[Document(id='3d37ee80-b6f6-40de-89f4-49ee1bc3e943', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='量子计算机在1980年代多处于理论推导状态。1994年彼得·秀尔提出量子质因数分解算法后[9]，证明量子计算机能运算离散对数[10]，而且速度远胜传统计算机。因为量子不像半导体只能记录0与1，可以同时表示多种状态。如果把半导体比喻成单一乐器，量子计算机就像交响乐团，一次运算可以处理多种不同状况，因此，一部40比特的量子计算机，就能在很短时间内解开1024位计算机花数十年解决的问题。因其对于现在通行于银行及网络等处的RSA加密算法可以破解而构成威胁，量子计算机成了热门话题，除了理论之外，也有不少学者着力于利用各种量子系统来实现量子计算机。'), Document(id='bf4717b8-5808-4c53-8a51-dc883c43da3f', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='量子贝叶斯诠释（英语：Quantum Bayesianism）\\\\n量子生物学\\\\n量子微积分（英语：Quantum calculus）\\\\n量子化学\\\\n量子混沌（英语：Quantum chaos）\\\\n量子认知（英语：Quantum cognition）\\\\n量子宇宙学\\\\n量子微分（英语：Quantum differential calculus）\\\\n量子动力学（英语：Quantum dynamics）\\\\n量子演化（英语：Quantum evolution）\\\\n量子几何（英语：Quantum geometry）\\\\n量子群\\\\n测量问题（英语：Measurement problem）\\\\n量子概率（英语：Quantum probability）\\\\n量子随机演算（英语：Quantum stochastic calculus）\\\\n量子时空（英语：Quantum spacetime）\\\\n量子技术\\\\n量子算法\\\\n量子放大器（英语：Quantum amplifier）\\\\n量子总线（英语：Quantum bus）\\\\n量子点\\\\n量子细胞自动机（英语：Quantum cellular automaton）\\\\n量子有限自动机\\\\n量子通道（英语：Quantum channel）'), Document(id='77ba01c1-dfd1-4a63-8205-934c458c8d3a', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='布洛赫球面乃一种对于二阶量子系统之纯态空间的几何表示法，是建立量子计算机的基础。\\\\n量子计算机（英语：Quantum computer）是一种使用量子逻辑进行通用计算的设备。但这与电子计算机（或称传统计算机）不同，量子计算用来存储数据的对象是量子比特，它使用量子算法操作数据。马约拉纳费米子的反粒子就是它自己本身的属性，此或许是促使量子计算机能被制造和实现的一个关键。[1]量子计算机在舆论中有时被过度渲染成无所不能或速度快数亿倍等，其实这种计算机是否强大，需要视问题而定。若该问题已经有提出速算的量子算法，只是仍然存在困难或受限于传统计算机无法执行，那量子计算机确实能达到前所未有的高速；若是没有发明算法的问题，则量子计算机表现与传统计算机无异甚至更差。[2]')]\\n\\n问题：如何解释量子计算？\\n\", additional_kwargs={}, response_metadata={})]\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'context': [Document(id='c296e22d-f7cf-48d2-b635-6a1a573f2660', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='量子计算机在1980年代多处于理论推导状态。1994年彼得·秀尔提出量子质因数分解算法后[9]，证明量子计算机能运算离散对数[10]，而且速度远胜传统计算机。因为量子不像半导体只能记录0与1，可以同时表示多种状态。如果把半导体比喻成单一乐器，量子计算机就像交响乐团，一次运算可以处理多种不同状况，因此，一部40比特的量子计算机，就能在很短时间内解开1024位计算机花数十年解决的问题。因其对于现在通行于银行及网络等处的RSA加密算法可以破解而构成威胁，量子计算机成了热门话题，除了理论之外，也有不少学者着力于利用各种量子系统来实现量子计算机。'), Document(id='63808346-9353-44c2-a796-2030a7865261', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='量子贝叶斯诠释（英语：Quantum Bayesianism）\\n量子生物学\\n量子微积分（英语：Quantum calculus）\\n量子化学\\n量子混沌（英语：Quantum chaos）\\n量子认知（英语：Quantum cognition）\\n量子宇宙学\\n量子微分（英语：Quantum differential calculus）\\n量子动力学（英语：Quantum dynamics）\\n量子演化（英语：Quantum evolution）\\n量子几何（英语：Quantum geometry）\\n量子群\\n测量问题（英语：Measurement problem）\\n量子概率（英语：Quantum probability）\\n量子随机演算（英语：Quantum stochastic calculus）\\n量子时空（英语：Quantum spacetime）\\n量子技术\\n量子算法\\n量子放大器（英语：Quantum amplifier）\\n量子总线（英语：Quantum bus）\\n量子点\\n量子细胞自动机（英语：Quantum cellular automaton）\\n量子有限自动机\\n量子通道（英语：Quantum channel）'), Document(id='94163c81-bb75-48b4-beee-623609059199', metadata={'source': 'https://zh.wikipedia.org/zh-cn/%E9%87%8F%E5%AD%90%E8%AE%A1%E7%AE%97%E6%9C%BA', 'title': '量子计算机 - 维基百科，自由的百科全书', 'language': 'zh-Hans-CN'}, page_content='布洛赫球面乃一种对于二阶量子系统之纯态空间的几何表示法，是建立量子计算机的基础。\\n量子计算机（英语：Quantum computer）是一种使用量子逻辑进行通用计算的设备。但这与电子计算机（或称传统计算机）不同，量子计算用来存储数据的对象是量子比特，它使用量子算法操作数据。马约拉纳费米子的反粒子就是它自己本身的属性，此或许是促使量子计算机能被制造和实现的一个关键。[1]量子计算机在舆论中有时被过度渲染成无所不能或速度快数亿倍等，其实这种计算机是否强大，需要视问题而定。若该问题已经有提出速算的量子算法，只是仍然存在困难或受限于传统计算机无法执行，那量子计算机确实能达到前所未有的高速；若是没有发明算法的问题，则量子计算机表现与传统计算机无异甚至更差。[2]')], 'question': '如何解释量子计算？'}\n"
     ]
    }
   ],
   "source": [
    "from langchain.schema.runnable import RunnablePassthrough\n",
    "from langchain_core.runnables import RunnableParallel\n",
    "\n",
    "partial_chain = RunnableParallel( \n",
    "    {\"context\": retriever, \"question\": RunnablePassthrough()}\n",
    ")\n",
    "response = partial_chain.invoke(\"如何解释量子计算？\")\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "chatbot",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
